
<!DOCTYPE html>
<html lang="">


<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
  <meta name="theme-color" content="#202020">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>
  
  
    <meta name="keywords" content>
  

  
    <meta name="description" content="Devops的定义">
  
  
  
  <link rel="icon" type="image/x-icon" href="/images/footer-logo.png">
  
  <title>Devops的定义 [ 51AIOps 专注于运维自动化  微信： kaipython ]</title>
  
    <!-- stylesheets list from config.yml -->
    
      <link rel="stylesheet" href="//cdn.bootcss.com/pure/1.0.0/pure-min.css">
    
      <link rel="stylesheet" href="/css/xoxo.css">
    
  
</head>


<body>
  <div class="nav-container">
    <nav class="home-menu pure-menu pure-menu-horizontal">
  <a class="pure-menu-heading" href="/">
    
    <span class="title" style="text-transform:none">51AIOps 专注于运维自动化  微信： kaipython</span>
  </a>

  <ul class="pure-menu-list clearfix">
      
          
            
              <li class="pure-menu-item"><a href="/" class="pure-menu-link">首页</a></li>
            
          
      
  </ul>
   
</nav>

  </div>

  <div class="container" id="content-outer">
    <div class="inner" id="content-inner" style='margin-left:-68px!important'>
      <div class="post-container">
  <article class="post" id="post">
    <header class="post-header text-center">
      <h1 class="title">
        Devops的定义
      </h1>
      <span>
        
        <time class="time" datetime="2020-08-11T16:00:00.000Z">
        2020-08-12
      </time>
        
      </span>
      <span class="slash">/</span>
      <span class="post-meta">
      <span class="post-tags">
        
      </span>
    </span>
      <span class="slash">/</span>
      <span class="read">
      <span id="busuanzi_value_page_pv"></span> 点击
    </span>
      <span class="slash">/</span>
    </header>

    <div class="post-content">
      <p>今天我们来聊一聊 DevOps 的“定义”。</p>
<p>近些年来，DevOps 在我们身边出现的频率越来越高了。各种大会上经常出现 DevOps 专场，行业内的公司纷纷在都招聘 DevOps 工程师，企业的 DevOps 转型看起来迫在眉睫，公司内部也要设计和开发 DevOps 平台……这么看来，DevOps 似乎无处不在。</p>
<p>可回过头来想想，关于 DevOps，很多问题我们真的想清楚了吗？所谓的 DevOps 平台，是否等同于自动化运维平台，或持续交付平台呢？DevOps 工程师的岗位描述中又需要写哪些技能要求呢？另外，该如何证明企业已经实现了 DevOps 转型呢？这些问题真是难倒了一众英雄好汉。说到底，听了这么久的 DevOps，它的“定义”到底是什么，好像从来没有人能说清楚。</p>
<p>现在，我们先来看看维基百科对 DevOps 的定义。不过，估计也没谁能看懂这到底是在说什么。</p>
<blockquote>
<p>DevOps（开发 Development 与运维 Operations 的组合词）是一种文化、一场运动或实践，强调在自动化软件交付流程及基础设施变更过程中，软件开发人员与其他信息技术（IT）专业人员彼此之间的协作与沟通。它旨在建立一种文化与环境，使构建、测试、软件发布得以快速、频繁以及更加稳定地进行。</p>
</blockquote>
<p>于是乎，每当提及 DevOps 是什么的时候，最常出现的比喻就是“盲人摸象”。有意思的是，DevOps 之父 Patrick 第一次参加 DevOpsDays 中国站活动的时候，也使用了这个比喻，看来在这一点上，中西方文化是共通的。毕竟每个人的视角都不相同，看到的 DevOps 自然也是千差万别。</p>
<p>DevOps 大潮汹涌而来，很多人都被裹挟着去探索和实践 DevOps，甚至有一种极端的看法认为一切好的实践都属于 DevOps，而一切不好的实践都是 DevOps 的反模式。</p>
<p>当年敏捷开始流行的时候，似乎也是相同的论调，但这种笼统的定义并不能帮助我们理清思路，甚至会带来很多负面的声音，比如 DevOps 就是开发干掉运维，又或者，DevOps 就是要让运维抛弃老本行，开始全面转型做开发。这让很多 IT 从业人员一度很焦虑。</p>
<p>客观来说，从 DevOps 运动诞生开始，那些先行者们就从来没有试图给 DevOps 下一个官方的定义。当然，这样做的好处很明显，由于不限定人群和范围，每个人都能从自己的立场来为 DevOps 做贡献，从而使 DevOps 所涵盖的范围越发宽广。</p>
<p>但是，坏处也是显而易见的。随着 DevOps 的不断发展，刚开始接触 DevOps 的人往往不得要领，只见树木不见森林，认知的偏差使得 DevOps 越发地神秘起来。</p>
<p>与其纠结于 DevOps 的定义，不如让我们一起尝试回归原始，来看看 DevOps 究竟要解决的是什么问题。</p>
<p>其实，DevOps 的秘密就来源于它的名字所代表的两种角色——开发和运维。那么这两种角色之间究竟有什么问题呢？我们从软件工程诞生以来所历经的三个重要发展阶段说起。</p>
<h3 id="瀑布式开发模式"><a href="#瀑布式开发模式" class="headerlink" title="瀑布式开发模式"></a>瀑布式开发模式</h3><p>](<a href="https://imgchr.com/i/0JIwqO" target="_blank" rel="noopener">https://imgchr.com/i/0JIwqO</a>)
<a href="https://imgchr.com/i/0JIaM6" target="_blank" rel="noopener"><img src="https://s1.ax1x.com/2020/10/05/0JIaM6.md.png" alt="0JIaM6.md.png"></a></p>
<p>瀑布式开发模式将软件交付过程划分成几个阶段，从需求到开发、测试和运维，它的理念是软件开发的规模越来越大，必须以一种工程管理的方式来定义每个阶段，以及相应的交付产物和交付标准，以期通过一种重流程，重管控，按照计划一步步推进整个项目的交付过程。</p>
<p>可是，随着市场环境和用户需求变化的不断加速，这种按部就班的方式有一个严重的潜在问题。</p>
<p>软件开发活动需要在项目一开始就确定项目目标、范围以及实现方式，而这个时间点往往是我们对用户和市场环境信息了解最少的时候，这样做出来的决策往往带有很大的不确定性，很容易导致项目范围不断变更，计划不断延期，交付上线时间不断推后，最后的结果是，即便我们投入了大量资源，却难以达到预期的效果。</p>
<p>从业界巨头 IBM 的统计数字来看，有 34% 的新 IT 项目延期交付，将近一半的应用系统因为缺陷导致线上回滚，这是一件多么令人沮丧的事情。</p>
<h3 id="敏捷式开发模式"><a href="#敏捷式开发模式" class="headerlink" title="敏捷式开发模式"></a>敏捷式开发模式</h3><p><img src="https://s1.ax1x.com/2020/10/05/0JIwqO.md.png" alt="0JIwqO.md.png"></p>
<p>基于这种问题，敏捷的思潮开始盛行。它的核心理念是，既然我们无法充分了解用户的真实需求是怎样的，那么不如将一个大的目标不断拆解，把它变成一个个可交付的小目标，然后通过不断迭代，以小步快跑的方式持续开发。</p>
<p>与此同时，将测试工作从研发末端的一个独立环节注入整个开发活动中，对开发交付的内容进行持续验证，保证每次可交付的都是一个可用的功能集合，并且由于质量内建在研发环节中，交付功能的质量也是有保障的。</p>
<p>很显然，敏捷是一种更加灵活的研发模式。经常有人会问，敏捷会直接提升团队的开发速度吗？答案是否定的。试想一下，难道说采用了敏捷方法，研发编码的速度就会提高两倍甚至三倍吗？回想一下很多年前在 IT 行业广为流传的“人月神话”，我们就能发现正确的认知有多么重要。</p>
<p>敏捷之所以更快，根本原因在于持续迭代和验证节省了大量不必要的浪费和返工。</p>
<p>说到底，敏捷源于开发实践，敏捷的应用使得开发和测试团队抱团取暖。可是问题又来了，开发和测试团队发现，不管研发的速度变得多快，在软件交付的另一端，始终有一群人在冷冰冰地看着他们，一句“现在没到发布窗口”让多少新开发的功能倒在了上线的门槛上。</p>
<p>毕竟，无论开发了多少“天才”的功能，如果没有经过运维环节的部署上线，并最终发布给真实用户，那么这些功能其实并没有什么用。</p>
<h3 id="DevOps-模式"><a href="#DevOps-模式" class="headerlink" title="DevOps 模式"></a>DevOps 模式</h3><p><img src="https://s1.ax1x.com/2020/10/05/0JIdsK.png" alt="0JIdsK.png"></p>
<p>于是，活在墙的另一端的运维团队成了被拉拢的对象。这些在软件交付最末端的团队始终处于一种“背锅”的状态，他们也有改变的意愿，所以 DevOps 应运而生，也就是说，DevOps 最开始想要打破的就是开发和运维之间的对立和隔阂。</p>
<p>在传统模式下，度量开发团队效率的途径就是看开发完成了多少需求。于是，开发为了达成绩效目标，当然也是为了满足业务需求，不断地堆砌新功能，却很少有时间认真思考这些功能的可运维性和可测试性，只要需求状态流转到开发完成就万事大吉了。</p>
<p>而对于运维团队而言，他们的考核指标却是系统的稳定性、可用性和安全性。但现代 IT 系统是如此复杂，以至于每一次的上线发布都是一场战役，整个团队如临大敌，上线失败的焦虑始终如影随形。</p>
<p>很多时候，我们并不知道上线之后会发生什么，只能按照部署手册一步步操作，完成之后就听天由命。所以，每逢大促活动，就会有各种“拜服务器教”的照片广为流传。</p>
<p>另一方面，在无数次被开发不靠谱的功能缺陷蹂躏得体无完肤之后，运维团队意识到，变更才是影响他们绩效目标的最大敌人。于是，预先设立的上线窗口就成了运维团队的自留地，不断抬高的上线门槛也使得开发团队的交付变成了不可能完成的任务，最后，“互相伤害”就成了这个故事注定的结局。</p>
<p>即便到了今天，部署上线在大多数公司依然是一件很神圣的事。</p>
<p>从一开始想要促进开发和运维的协作，团队慢慢发现，其实在整个软件交付过程中，不仅只有开发和运维，业务也是重要的一环。</p>
<p>比方说，如果业务制定了一个不靠谱的需求，那么无论开发和运维怎样协作，得到的终究是一个不靠谱的结果，以及对人力的浪费。可是业务并不清楚用户的真实情况，于是运维团队慢慢转向运营团队，他们需要持续不断地把线上的真实数据和用户行为及时地反馈给需求团队，来帮助需求团队客观评估需求的价值，并及时作出有利于产品发展的调整，这样一来，业务也被引入到了 DevOps 之中，甚至诞生了 BizDevOps 这样一个专门的词汇。</p>
<p>那么，既然沟通协作放之四海皆准，安全也开始积极地参与进来。安全不再是系统上线发布之后的“定时炸弹”，而是介入到整个软件开发过程中，在每个过程中注入安全反馈机制，来帮助团队在第一时间应对安全风险，那么，对于安全团队来说，DevSecOps就成了他们眼中的 DevOps。</p>
<p>这样的例子比比皆是，包括职能部门、战略部门等，都纷纷加入其中，使得 DevOps 由最开始的点，扩展为线，再到面，不断发展壮大。每个人都参与其中，这使得 DevOps 成了每一个 IT 从业人员都需要学习和了解的知识和技能体系。</p>
<h2 id="认识-DevOps"><a href="#认识-DevOps" class="headerlink" title="认识 DevOps"></a>认识 DevOps</h2><p>DevOps 这几年一直在不断地演化，那么它到底是什么呢？</p>
<p><strong>目前，人们对 DevOps 的看法，可以大致概括为 DevOps 是一组技术，一个职能、一种文化，和一种组织架构四种。</strong></p>
<p><strong>第一，DevOps 是一组技术，包括：自动化运维、持续交付、高频部署、Docker 等内容。</strong></p>
<p>但是，如果你仅仅将 DevOps 认为是一组技术的集合的话，就有一些片面。任何技术都是为了解决某些问题而被创造出来的。比如 Docker，就是为了解决 DevOps 所提倡的“基础设施即代码”这个问题，而被创造出来的。</p>
<p>从这个角度来看的话，DevOps 的范畴应该远远大于一组技术了。</p>
<p>其实，DevOps 是一组技术这个观点，还是只站在了工程师角度去思考问题而得出的结论。虽然“DevOps”中“Dev”和“Ops”这两个角色都是工程师，但是其本质还是希望跳出工程师的惯性思维来看待问题。</p>
<p><strong>第二，DevOps 是一个职能，这也是我在各个场合最常听到的观点。</strong></p>
<p>你的公司有没有或者正准备成立一个叫作 DevOps 的部门，并将这个部门的工程师命名为 DevOps 工程师？至少在各大招聘网站上，是随处可见这样的职位，而招聘要求往往就是：会 Ops 技能的 Dev，或者会 Dev 技能的 Ops；或者干脆叫全栈工程师。</p>
<p>“DevOps 是一个职能”这个观点，源于设施的日趋完善，云服务的流行，以及各类开源工具的广泛使用，使传统 Ops 的工作重心发生了变化，使企业产生了不再需要 Ops 的错觉。</p>
<p>但这个观点也是错误的，原因就是忽略了 Dev 与 Ops 本质上是不同的，也就是他们掌握的技能是不同。</p>
<p>虽然在 DevOps 看来，Dev 和 Ops 的最终目标是一致的，都是为了快速向客户提供高质量的产品，但其达到目标的手段和方法是不一样的。比如，Ops 往往需要更多的在线处理问题的经验，而这未必是 Dev 所具备的。</p>
<p>所以，简单地把 DevOps 看做是一个职能，是一个彻底错误的观点。</p>
<p><strong>第三，DevOps 是一种文化，推倒 Dev 与 Ops 之间的阻碍墙。</strong></p>
<p>DevOps 是通过充分的合作解决责任模糊、相互推诿的问题和矛盾。在著名的演讲《每天部署 10 次以上：Flickr 公司的 Dev 与 Ops 的合作》 中，就明确的指出工具和文化是他们成功的原因。</p>
<p>其实，DevOps 通常想要告诉我们的是：什么行为是值得被鼓励的，而什么行为需要被惩罚。通过这样的方法，DevOps 可以促使我们形成良好的做事习惯，也就是 DevOps 文化。</p>
<p>所以，我们可以发现引入 DevOps 的组织，其实都是希望塑造这样的一种：信任、合作、沟通、学习、分享、共担等鼓励协作的文化。</p>
<p><strong>第四，DevOps 是一种组织架构，将 Dev 和 Ops 置于一个团队内，一同工作，同化目标，以达到 DevOps 文化地彻底贯彻。</strong></p>
<p>这看起来确实没有什么问题，而且敏捷团队往往都是这么去做的。但是，从另一方面来看，Ops 作为公司的公共研发资源，往往与 Dev 的配比是不成比例。所以，虽然我们希望每一个敏捷团队都有 Ops，但这可能是一种奢求。</p>
<p>但是，敏捷团队也说了，不一定是要有一个专职 Ops 人员，只要有负担这个角色职责的成员存在即可。这当然也讲得通，但可能真正的执行效果就没有 DevOps 所设想的那么好了。</p>
<p>所以，DevOps 是一种组织架构，这种说法，也对也不对，主要视组织的具体情况而定。</p>
<p>说到最后，我还是希望基于我对 DevOps 的理解，给出一个我自己的“定义”：</p>
<blockquote>
<p>DevOps 是通过平台（Platform）、流程（Process）和人（People）的有机整合，以 C（协作）A（自动化）L（精益）M（度量）S（共享）文化为指引，旨在建立一种可以快速交付价值并且具有持续改进能力的现代化 IT 组织。</p>
</blockquote>

    </div>

  </article>
  <div class="toc-container">
    
  <div id="toc" class="toc-article">
    <strong class="toc-title">目录</strong>
    <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#瀑布式开发模式"><span class="toc-text">瀑布式开发模式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#敏捷式开发模式"><span class="toc-text">敏捷式开发模式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#DevOps-模式"><span class="toc-text">DevOps 模式</span></a></li></ol><li class="toc-item toc-level-2"><a class="toc-link" href="#认识-DevOps"><span class="toc-text">认识 DevOps</span></a>
  </li></div>


  </div>
</div>
<script type="text/javascript" src="//rf.revolvermaps.com/0/0/8.js?i=5sr5du46f27&amp;m=0&amp;c=ff0000&amp;cr1=ffffff&amp;f=arial&amp;l=33" async="async"></script>
<div class="copyright">
    <span>本作品采用</span>
    <a href="https://creativecommons.org/licenses/by/4.0/">知识共享署名 4.0 国际许可协议</a>
    <span>进行许可。 转载时请注明原文链接。</span>
</div>


  
    <div class="post-nav" style="margin-left:-168px;">
      <div class="post-nav-item post-nav-next">
        
          <span>〈 </span>
          <a href="/2020/08/12/如何利用监控保障发布质量/" rel="next" title="如何利用监控保障发布质量">
          如何利用监控保障发布质量
          </a>
        
      </div>
  
      <div class="post-nav-item post-nav-prev">
          
          <a href="/2020/08/14/Gin框架路由的拆分/" rel="prev" title="Gin框架路由的拆分和注册">
            Gin框架路由的拆分和注册
          </a>
          <span>〉</span>
        
      </div>
    </div>
  


	
	<div style="width:109%; margin-left:-144px" id="lv-container" data-id="city" data-uid="MTAyMC80OTg5NS8yNjM4Ng==">
	<script type="text/javascript">
   	   (function(d, s) {
       		var j, e = d.getElementsByTagName(s)[0];

       		if (typeof LivereTower === 'function') { return; }

       		j = d.createElement(s);
       		j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
       		j.async = true;

       		e.parentNode.insertBefore(j, e);
   	   })(document, 'script');
	</script>
	<noscript> 为正常使用来必力评论功能请激活JavaScript</noscript>
        </div>
	



    </div>

    

  </div>
  <footer class="footer text-center">
    <div id="bottom-inner">
        <a class="bottom-item" href target="_blank">GitHub</a> |
        <a class="bottom-item" href>友情链接</a> |
        <a class="bottom-item" href="https://hexo.io" target="_blank">Powered by hexo</a> |
        <a class="bottom-item" href="https://github.com/fooying/hexo-theme-xoxo-plus" target="_blank">Theme xoxo-plus</a> |
        <a class="bottom-item" href="/atom.xml">订阅</a>
    </div>
</footer>

  

<script>
  (function(window, document, undefined) {

    var timer = null;

    function returnTop() {
      cancelAnimationFrame(timer);
      timer = requestAnimationFrame(function fn() {
        var oTop = document.body.scrollTop || document.documentElement.scrollTop;
        if (oTop > 0) {
          document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
          timer = requestAnimationFrame(fn);
        } else {
          cancelAnimationFrame(timer);
        }
      });
    }

    var hearts = [];
    window.requestAnimationFrame = (function() {
      return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback) {
          setTimeout(callback, 1000 / 60);
        }
    })();
    init();

    function init() {
      css(".heart{z-index:9999;width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: absolute;}.heart:after{top: -5px;}.heart:before{left: -5px;}");
      attachEvent();
      gameloop();
      addMenuEvent();
    }

    function gameloop() {
      for (var i = 0; i < hearts.length; i++) {
        if (hearts[i].alpha <= 0) {
          document.body.removeChild(hearts[i].el);
          hearts.splice(i, 1);
          continue;
        }
        hearts[i].y--;
        hearts[i].scale += 0.004;
        hearts[i].alpha -= 0.013;
        hearts[i].el.style.cssText = "left:" + hearts[i].x + "px;top:" + hearts[i].y + "px;opacity:" + hearts[i].alpha + ";transform:scale(" + hearts[i].scale + "," + hearts[i].scale + ") rotate(45deg);background:" + hearts[i].color;
      }
      requestAnimationFrame(gameloop);
    }

    /**
     * 给logo设置点击事件
     * 
     * - 回到顶部
     * - 出现爱心
     */
    function attachEvent() {
      var old = typeof window.onclick === "function" && window.onclick;
      var logo = document.getElementById("logo");
      if (logo) {
        logo.onclick = function(event) {
          returnTop();
          old && old();
          createHeart(event);
        }
      }
      
    }

    function createHeart(event) {
      var d = document.createElement("div");
      d.className = "heart";
      hearts.push({
        el: d,
        x: event.clientX - 5,
        y: event.clientY - 5,
        scale: 1,
        alpha: 1,
        color: randomColor()
      });
      document.body.appendChild(d);
    }

    function css(css) {
      var style = document.createElement("style");
      style.type = "text/css";
      try {
        style.appendChild(document.createTextNode(css));
      } catch (ex) {
        style.styleSheet.cssText = css;
      }
      document.getElementsByTagName('head')[0].appendChild(style);
    }

    function randomColor() {
      // return "rgb(" + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + ")";
      return "#F44336";
    }

    function addMenuEvent() {
      var menu = document.getElementById('menu-main-post');
      if (menu) {
        var toc = document.getElementById('toc');
        if (toc) {
          menu.onclick = function() {
            if (toc) {
              if (toc.style.display == 'block') {
                toc.style.display = 'none';
              } else {
                toc.style.display = 'block';
              }
            }
          };
        } else {
          menu.style.display = 'none';
        }
      }
    }

  })(window, document);
</script>

  



  

</body>
</html>
